package org.springblade.task.job.report.user;

import com.baomidou.mybatisplus.annotation.TableName;
import com.google.common.collect.Lists;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.utils.CommonUtil;
import org.springblade.common.utils.DateUtils;
import org.springblade.modules.userAnalysis.entity.DailyUserRankingReport;
import org.springblade.modules.userAnalysis.service.IDailyUserRankingReportService;
import org.springblade.task.base.entity.BaseUser;
import org.springblade.task.base.entity.BaseUserReadingDataLog;
import org.springblade.task.base.param.BaseOrderBookParam;
import org.springblade.task.base.param.BaseUserParam;
import org.springblade.task.base.param.BaseUserReadingDataLogParam;
import org.springblade.task.base.service.*;
import org.springblade.task.base.vo.*;
import org.springblade.task.job.base.BaseTaskInfoJob;
import org.springblade.task.quartz.entity.QuartzTask;
import org.springblade.task.quartz.service.IQuartzTaskService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @Title: 用户分析-每日用户排行
 * @author syncwt
 * @version V1.0
 */
@Component
public class DailyUserRankingReportJob {

	private static Logger logger = LoggerFactory.getLogger(BaseTaskInfoJob.class);

	@Autowired
	private IQuartzTaskService quartzTaskService;
	@Autowired
	private IBaseUserService baseUserService;
	@Autowired
	private IBaseUserReadingDataLogService baseUserReadingDataLogService; // 用户阅读
	@Autowired
	private IBaseNetChapterOrderService BaseNetChapterOrderService; // 网文订单
	@Autowired
	private IBaseEbookOrderService BaseEbookOrderService; // 电子书订单
	@Autowired
	private IBaseAudioChapterOrderService BaseAudioChapterOrderService; //有声订单
	@Autowired
	private IDailyUserRankingReportService userRankingReportService;
	@Resource
	private ThreadPoolTaskExecutor threadPoolTaskExecutor;
	private static final int MAX_WAIT_TIME = 50; // future 超时时间50秒

	/**
	 * 1、简单任务示例（Bean模式）
	 */
	@XxlJob("userRankingReportJob")
	public ReturnT<String> userRankingReportJob(String param) throws Exception {
		System.out.println(DateUtils.currentDateTime() + " -- XXL-JOB, Hello World.");
		System.err.println("执行静态定时任务日期: " + DailyUserRankingReportJob.class.getSimpleName());
		QuartzTask quartzTask = quartzTaskService.queryByTaskName(DailyUserRankingReportJob.class.getSimpleName(), -7);
		// 今日
		String todayDate = DateUtils.crutDate();
		String taskDate = quartzTask.getTaskDate();
		while (taskDate.compareTo(todayDate) < 0) {
			// 当时间大于5点，跳出执行
//			if (DateUtils.getHour24() > 5) {
//				break;
//			}
			// 再加一个凌晨1点判断
			currMethod(taskDate);
			// 增加1天
			taskDate = DateUtils.dateAddDay(taskDate, 1);
		}
		quartzTask.setTaskDate(taskDate);
		quartzTaskService.saveQuartzTask(quartzTask);
		return ReturnT.SUCCESS;
	}

	/**
	 *
	 * @param taskDate
	 */
	public void currMethod(String taskDate) {

		int count = baseUserService.count();
		BaseUserParam param = new BaseUserParam();
		param.setCount(count);
		int currPage = 0;
		while (currPage < param.getTotalPage()) {
			param.setTableName(CommonUtil.getTableName(new BaseUser()));
			List<BaseUserVO> baseUserList = baseUserService.queryList(param);
			List<Future<List<DailyUserRankingReport>>> futureResults = Lists.newArrayList();
			try {
				// 内存分页，每页取最大值
				int batchReadLimit = Math.max(baseUserList.size() / 5000, 1000);
				List<List<BaseUserVO>> resultPageParts = Lists.partition(baseUserList, batchReadLimit);
				CountDownLatch countDownLatch = new CountDownLatch(resultPageParts.size());

				for (List<BaseUserVO> userList : resultPageParts) {
					futureResults.add(threadPoolTaskExecutor.submit(new QueryThreadTask(countDownLatch, taskDate, userList)));
				}
				countDownLatch.await(MAX_WAIT_TIME, TimeUnit.SECONDS);
			} catch (Exception e) {
				e.getMessage();
			}
			currPage ++;
		}


	}

	public void init() {
		logger.info("init");
	}

	public void destroy() {
		logger.info("destory");
	}


	// 内部类
	class QueryThreadTask implements Callable<List<DailyUserRankingReport>> {

		private CountDownLatch countDownLatch;
		private String taskDate;
		private List<BaseUserVO> userList;

		public QueryThreadTask(CountDownLatch countDownLatch, String taskDate, List<BaseUserVO> userList) {
			this.countDownLatch = countDownLatch;
			this.taskDate = taskDate;
			this.userList = userList;
		}

		@Override
		public List<DailyUserRankingReport> call() throws Exception {
			List<DailyUserRankingReport> listRpcResult = null;
			try {
				listRpcResult = userRankingReport(taskDate, userList);
			} catch (Exception e) {
			} finally {
				countDownLatch.countDown();
			}
			return listRpcResult;
		}

		/**
		 * 数据查询
		 *
		 * @return
		 */
		private List<DailyUserRankingReport> userRankingReport(String taskDate, List<BaseUserVO> userList) {

			List<String> pinList = new ArrayList<>();
			for (BaseUserVO baseUser : userList) {
				pinList.add(baseUser.getPin());
			}

			// 查询用户阅读数据
			BaseUserReadingDataLogParam logParam = new BaseUserReadingDataLogParam();
			logParam.setPinList(pinList);
			logParam.setStartDate(DateUtils.getDateStartTime(taskDate));
			logParam.setEndDate(DateUtils.getDayEndTime(taskDate));
			System.out.println(CommonUtil.getTableName(new BaseUserReadingDataLog()));
			List<BaseUserReadingDataLogVO> logVOList = baseUserReadingDataLogService.queryUserReadingDataCount(logParam);
			Map<String, BaseUserReadingDataLogVO> readBookMap = new HashMap<>();
			for (BaseUserReadingDataLogVO vo : logVOList) {
				readBookMap.put(vo.getPin(), vo);
			}

			// 查询订单网文电子书
			BaseOrderBookParam orderParam = new BaseOrderBookParam();
			BeanUtils.copyProperties(logParam, orderParam);
			List<BaseNetChapterOrderVO> onlineOrderList = BaseNetChapterOrderService.queryOnlineBookUserOrderCount(orderParam);
			Map<String, BaseNetChapterOrderVO> onlineOrderMap = new HashMap<>();
			for (BaseNetChapterOrderVO vo : onlineOrderList) {
				onlineOrderMap.put(vo.getPin(), vo);
			}

			// 查询订单电子书
			List<BaseEbookOrderVO> ebookOrderList = BaseEbookOrderService.queryEBookUserOrderCount(orderParam);
			Map<String, BaseEbookOrderVO> ebookOrderMap = new HashMap<>();
			for (BaseEbookOrderVO vo : ebookOrderList) {
				ebookOrderMap.put(vo.getPin(), vo);
			}

			// 查询订单有声
			List<BaseAudioChapterOrderVO> audioBookOrderList = BaseAudioChapterOrderService.queryAudioBookUserOrderCount(orderParam);
			Map<String, BaseAudioChapterOrderVO> audioBookOrderMap = new HashMap<>();
			for (BaseAudioChapterOrderVO vo : audioBookOrderList) {
				audioBookOrderMap.put(vo.getPin(), vo);
			}

			List<DailyUserRankingReport> userRankingReportList = new ArrayList<>();
			DailyUserRankingReport report = null;
			for (BaseUser baseUser : userList) {
				report = new DailyUserRankingReport();
				report.setPin(baseUser.getPin());
				report.setNickName(baseUser.getNickName());

				BaseUserReadingDataLogVO userReadingDataLogVO = readBookMap.get(baseUser.getPin());
				int readNum = 0;
				int readHour = 0;
				int playHour = 0;
				if (null != userReadingDataLogVO) {
					readNum = userReadingDataLogVO.getReadCount();
					readHour = userReadingDataLogVO.getReadLength();
					playHour = userReadingDataLogVO.getPlayLength();
				}

				int orderNum = 0;
				int orderAmount = 0;
				int buyNum = 0;
				BaseNetChapterOrderVO onlineOrderVO = onlineOrderMap.get(baseUser.getPin());
				if (null != onlineOrderVO) {
					orderNum = +onlineOrderVO.getOrderNum();
					orderAmount = +onlineOrderVO.getAmount();
					buyNum = +onlineOrderVO.getOrderNum();
				}

				BaseEbookOrderVO ebookOrderVO = ebookOrderMap.get(baseUser.getPin());
				if (null != ebookOrderVO) {
					orderNum = +ebookOrderVO.getOrderNum();
					orderAmount = +ebookOrderVO.getAmount();
					buyNum = +ebookOrderVO.getOrderNum();
				}
				BaseAudioChapterOrderVO audioBookOrderVO = audioBookOrderMap.get(baseUser.getPin());
				if (null != audioBookOrderVO) {
					orderNum = +audioBookOrderVO.getOrderNum();
					orderAmount = +audioBookOrderVO.getAmount();
					buyNum = +audioBookOrderVO.getOrderNum();
				}

				report.setDate(taskDate);
				report.setOrderNum(orderNum);
				report.setOrderAmount(orderAmount);
				report.setBuyNum(buyNum);
				report.setReadNum(readNum);
				report.setReadHour(readHour);
				report.setPlayHour(playHour);
				userRankingReportList.add(report);
			}
			userRankingReportService.saveBatch(userRankingReportList);
			return null;
		}
	}


}
